package com.miniits.base.all;

import org.jsoup.Jsoup;
import org.jsoup.nodes.Document;
import org.jsoup.nodes.Element;
import org.jsoup.select.Elements;
import org.openqa.selenium.By;
import org.openqa.selenium.JavascriptExecutor;
import org.openqa.selenium.WebDriver;
import org.openqa.selenium.chrome.ChromeDriver;
import org.openqa.selenium.chrome.ChromeOptions;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Async;
import org.springframework.stereotype.Service;
import org.springframework.util.ObjectUtils;
import org.springframework.util.StringUtils;

import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.util.*;
import java.util.stream.Collectors;

import static com.miniits.base.all.BetController.T_U;
import static com.miniits.base.all.BetController.users;
import static com.miniits.base.utils.BetServiceUtil.*;

@Service
public class BetPull {

    private static final Logger LOGGER = LoggerFactory.getLogger(BetPull.class);

    public static final String sTime = "12:00:00";

    public static final String allUseTime = "14:00:00";

    private Map<String, Boolean> so = new HashMap<String, Boolean>() {{
        put("1", true);
        put("2", true);
        put("3", true);
        put("4", true);
        put("5", true);
    }};

    private Map<String, Integer> groupOrder = new HashMap<String, Integer>() {{
        put("1", 0);
        put("2", 0);
        put("3", 0);
        put("4", 0);
        put("5", 0);
    }};

    private Map<String, Integer> refreshNum = new HashMap<String, Integer>() {{
        put("1", 0);
        put("2", 0);
        put("3", 0);
        put("4", 0);
        put("5", 0);
    }};

    private Map<String, Integer> totalOrder = new HashMap<String, Integer>() {{
        put("1", 0);
        put("2", 0);
        put("3", 0);
        put("4", 0);
        put("5", 0);
    }};

    Map<String, Integer> bets = new HashMap<>();

    private Map<String, Long> startTime = new HashMap<>();

    public long endTime = 2 * 60 * 60 * 1000;

    public Bet bet = new Bet(1000);

    @Autowired
    public BetService betService;

    @Async
    public void startRun(long curr, String page) throws Exception {
        for (String k : totalOrder.keySet()) {
            totalOrder.put(k, 0);
        }
        startTime.put(page, curr);
        open(page);
    }

    public void open(String page) throws Exception {
        ChromeOptions opiions = new ChromeOptions();
        opiions.addArguments("--start-maximized");
        WebDriver driver = new ChromeDriver(opiions);
        driver.get(T_U);
        User user = users.get(page);
        /**
         * 获取首页弹窗，并关闭
         * 正常延时 2000 毫秒
         */
        try {
            Thread.sleep(2000);
            driver.findElement(By.cssSelector("div.ad-title>a.close")).click();
        } catch (Exception e) {
            try {
                driver.findElement(By.xpath("//body")).click();
            } catch (Exception ex) {
                try {
                    driver.findElement(By.cssSelector("body > app-root > app-home > div.dialog-wrap > div > div.ad-title > a.close")).click();
                } catch (Exception e1) {
                }
            }
        }

        /**
         * 清除用户名，密码
         * 正常延时 2000 毫秒
         */
        Thread.sleep(1000);
        String loginNode = "//div[@class='main']";
        By nameNode = By.xpath(loginNode + "/child::input[1]");
        By pwNode = By.xpath(loginNode + "/child::input[2]");
        By loginBtnNode = By.cssSelector("div.main>a.btn1");
        try {
            driver.findElement(nameNode).clear();
            driver.findElement(nameNode).sendKeys(user.getUserName());
            driver.findElement(pwNode).clear();
            driver.findElement(pwNode).sendKeys(user.getPassword());
        } catch (Exception e) {
            reOpen(driver, page);
        }
        Thread.sleep(1000);
        try {
            driver.findElement(loginBtnNode).click();
        } catch (Exception e) {
            reOpen(driver, page);
        }

        Thread.sleep(1500);
//        点击同意协议
        try {
            driver.findElement(By.cssSelector("div.buttons>a.btn1")).click();
        } catch (Exception e) {
            Thread.sleep(2000);
            try {
                driver.findElement(By.cssSelector("a.btn1")).click();
            } catch (Exception e1) {
                try {
                    driver.findElement(By.cssSelector("body > app-root > app-agreement > div > div > div > div.buttons > a.btn1")).click();
                } catch (Exception e2) {
                    reOpen(driver, page);
                }
            }
        }
        Thread.sleep(500);
        // 关闭多个窗口
        for (int i = 0; i < 5; i++) {
            try {
                Thread.sleep(100);
                driver.findElement(By.cssSelector("div.notice-box>a.close")).click();
            } catch (Exception e) {
            }
        }

        // 极速飞艇
        try {
            Thread.sleep(500);
            driver.findElement(By.xpath("//div[@class='main1250']/div[@class='navbar']/a[2]")).click();
        } catch (Exception e) {
            Thread.sleep(500);
            try {
                driver.findElement(By.cssSelector("body > app-root > app-game > nav > div > div.navbar > a.hot.active")).click();
            } catch (Exception e1) {
            }
        }

        // 点击单号1-10
        clickOneToTen(driver);
        List<Bet> data = betService.findAll();
        if (data.size() >= 1) {
            bet = data.get(0);
        }

        /**
         * 判断是否到了12点
         * todo 上线修改 成  12:00:00
         */
        setSleepTime(sTime);
        Map<String, Integer> bets = randomUtil(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
        startBet(driver, page);
    }

    /**
     * 开始下单，并开始计时，10秒内下一单，
     * 不能多，不能少
     *
     * @param driver
     * @param page
     * @throws InterruptedException
     */
    public void startBet(WebDriver driver, String page) throws Exception {

        /**
         * 判断当前组是否多下注完了
         */
        if (ObjectUtils.isEmpty(bets)) {
            over();
        }
//        Map<String, Integer> bets = randomUtil(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
//        if (so.get("1") && so.get("2") && so.get("3") && so.get("4") && so.get("5")) {
//            so.put("1", false);
//            so.put("2", false);
//            so.put("3", false);
//            so.put("4", false);
//            so.put("5", false);
//            LOGGER.info("重新计算");
//            bets = randomUtil(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
//        }
        // 判断一组内是否已经下了6单，不能多下
        if (groupOrder.get(page) >= 6) {
            Thread.sleep(1000);
            LOGGER.info("{}大于6单了，当前第{}单", page, groupOrder.get(page));
            String tt = closed(driver);
            if (null != tt && tt.equals("已封盘")) {
                groupOrder.put(page, 0);
                long sleepTime = closedTime(driver);
                if (sleepTime > 1000) {
                    Thread.sleep(sleepTime - 1000);
                }
            } else {
                String y = tt.replace("秒", "");
                y = StringUtils.isEmpty(y) ? "0" : y;
                Thread.sleep(Long.valueOf(y) * 1000 + 500);
            }
            startBet(driver, page);
        }
        /**
         * 判断是否到了14点
         */
        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd 14:00:00");
        String currentTime = null;
        try {
            currentTime = sdf.format(new Date());
        } catch (Exception e) {
        }

        SimpleDateFormat sDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss"); //加上时间
        try {
            Date date = sDateFormat.parse(currentTime);
            long yusj = date.getTime() - System.currentTimeMillis();
            if (yusj < 0) {
                // TODO: 2019/2/23 上线放开
//                LOGGER.info("14------点了");
//                driver.close();
//                return;
            }
        } catch (ParseException px) {
        }

        // 查看是否已封盘,并查看剩余封盘时间
        String text = closed(driver);
        if (null != text && text.equals("已封盘")) {
            groupOrder.put(page, 0);
            long sleepTime = closedTime(driver);
            LOGGER.info("封盘时间，{}", sleepTime);
            Thread.sleep(sleepTime);
        }
        // 一单用时开始时间
        long startDate = System.currentTimeMillis();
        // 输入下单金额
        String bm = String.valueOf(bet.getBetNum());
        try {
            Thread.sleep(500);
            driver.findElement(By.xpath("//div[@class='bet-number']/input")).clear();
            driver.findElement(By.xpath("//div[@class='bet-number']/input")).sendKeys(bm);
        } catch (Exception e) {
            try {
                driver.findElement(By.xpath("//div[@class='bet-number']/input")).clear();
                driver.findElement(By.xpath("//div[@class='bet-number']/input")).sendKeys(bm);
            } catch (Exception e1) {
            }
        }

        By tableNodes = By.xpath("//div[@class=table-wrap]");

        Thread.sleep(1000);
        if (page.equals("1")) {
            table1(driver, bets, tableNodes, page);
            while (againSelect(driver, 1)) {
                table1(driver, bets, tableNodes, page);
            }
        }
        if (page.equals("2")) {
            table2(driver, bets, tableNodes, page);
            while (againSelect(driver, 2)) {
                table2(driver, bets, tableNodes, page);
            }
        }
        if (page.equals("3")) {
            table3(driver, bets, tableNodes, page);
            while (againSelect(driver, 3)) {
                table3(driver, bets, tableNodes, page);
            }
        }
        if (page.equals("4")) {
            table4(driver, bets, tableNodes, page);
            while (againSelect(driver, 4)) {
                table4(driver, bets, tableNodes, page);
            }
        }
        if (page.equals("5")) {
            table5(driver, bets, tableNodes, page);
            while (againSelect(driver, 5)) {
                table5(driver, bets, tableNodes, page);
            }
        }

        /**
         * 查看是否已封盘
         * 确认 --> 提交订单 --> 结束
         * 正常延时 2800 毫秒
         * 异常延时 2800 + 1000 = 3800 毫秒（3.8秒）
         */
        text = closed(driver);
        if (text.equals("已封盘")) {
            groupOrder.put(page, 0);
            startBet(driver, page);
        }
        try {
            Thread.sleep(1000);
            driver.findElement(By.cssSelector("div.bet-number>a.bet-btn")).click();
        } catch (Exception e) {
            Thread.sleep(1000);
            try {
                driver.findElement(By.xpath("/html/body/app-root/app-game/div/div[2]/div[2]/app-play/div[2]/div[1]/a[7]")).click();
            } catch (Exception e1) {
            }
        }

        Thread.sleep(1000);
        try {
            driver.findElement(By.cssSelector("div.submit>a")).click();
        } catch (Exception e) {
        }

        totalOrder.put(page, totalOrder.get(page) + 1);
        groupOrder.put(page, groupOrder.get(page) + 1);
        /**
         * 判断当前组是否多下注完了
         */
        over();
        // 从十二点开始，到十四点结束,耗时 2 小时
        if (System.currentTimeMillis() - startTime.get(page) < endTime) {
            try {
                Thread.sleep(300);
                driver.findElement(By.xpath("//div[@class='header']/a")).click();
            } catch (Exception e) {
            }
            Thread.sleep(500);
            long endDate = System.currentTimeMillis();
            long useDate = endDate - startDate;

            LOGGER.info("{}组-已提交-{}-单，-剩余时间（分钟），{}", page, totalOrder.get(page), (endTime - (get12(allUseTime) - System.currentTimeMillis())) / 1000 / 60);
            // 判断剩余时间
            if (10 * 1000 > useDate && useDate < 8600) {
                so.put(page, true);
                Thread.sleep(8600 - useDate);
                LOGGER.info("{}组，休眠时间{}", page, 8600 - useDate);
            }
            LOGGER.info("-----------------------------------------------------------------------------------------");
            startBet(driver, page);
        }
//        refreshNum = 0;
        refreshNum.put(page, 0);
        try {
            driver.close();
        } catch (Exception e) {
        }
    }

    public void table1(WebDriver driver, Map<String, Integer> bets, By tableNodes, String page) throws Exception {
        assertionOneToTen(driver);
        String text = closed(driver);
        if (StringUtils.isEmpty(text)) {
            open(page);
        }
        if (null == text) {
            LOGGER.info("text,为空啦");
            open(page);
        }
        if (text.equals("已封盘")) {
            groupOrder.put(page, 0);
            LOGGER.info(page + "已封盘,已下{}", groupOrder.get(page));
            startBet(driver, page);
        }
        clearBet(driver, tableNodes, Arrays.asList("1", "2", "3"));

        Integer gj = bets.get("gj");
        Integer yj = bets.get("yj");
        Integer dsm = bets.get("dsm");

        LOGGER.info("1组号码：{}-{}-{}", gj, yj, dsm);
        /**
         * 开始点击需要下注的号码
         * 正常延时 900 毫秒
         * 异常延时 900 + 600 = 1500 毫秒（1.5秒）
         */
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[1]/tbody/tr[" + gj + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[1]/tbody/tr[" + gj + "]")).click();
            } catch (Exception e1) {
            }
        }
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[2]/tbody/tr[" + yj + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[2]/tbody/tr[" + yj + "]")).click();
            } catch (Exception e1) {
            }
        }
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[3]/tbody/tr[" + dsm + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[3]/tbody/tr[" + dsm + "]")).click();
            } catch (Exception e1) {
            }
        }
    }

    public void table2(WebDriver driver, Map<String, Integer> bets, By tableNodes, String page) throws Exception {
        assertionOneToTen(driver);
        String text = closed(driver);
        if (StringUtils.isEmpty(text)) {
            open(page);
        }
        if (text.equals("已封盘")) {
            groupOrder.put(page, 0);
            LOGGER.info(page + "已封盘,已下{}", groupOrder.get(page));
            startBet(driver, page);
        }

        clearBet(driver, tableNodes, Arrays.asList("4", "5", "6"));

        Integer dsm_ = bets.get("dsm_");
        Integer dwm = bets.get("dwm");
        Integer dlm = bets.get("dlm");
        LOGGER.info("2组号码：{}-{}-{}", dsm_, dwm, dlm);
        /**
         * 开始点击需要下注的号码
         * 正常延时 900 毫秒
         * 异常延时 900 + 600 = 1500 毫秒（1.5秒）
         */
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[4]/tbody/tr[" + dsm_ + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[4]/tbody/tr[" + dsm_ + "]")).click();
            } catch (Exception e1) {
            }
        }
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[5]/tbody/tr[" + dwm + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[5]/tbody/tr[" + dwm + "]")).click();
            } catch (Exception e1) {
            }
        }
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[6]/tbody/tr[" + dlm + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[6]/tbody/tr[" + dlm + "]")).click();
            } catch (Exception e1) {
            }
        }

    }

    public void table3(WebDriver driver, Map<String, Integer> bets, By tableNodes, String page) throws Exception {
        assertionOneToTen(driver);

        String text = closed(driver);
        if (StringUtils.isEmpty(text)) {
            open(page);
        }
        if (text.equals("已封盘")) {
            groupOrder.put(page, 0);
            LOGGER.info(page + "已封盘,已下{}", groupOrder.get(page));
            startBet(driver, page);
        }

        clearBet(driver, tableNodes, Arrays.asList("7", "8"));

        Integer dqm = bets.get("dqm");
        Integer dbm = bets.get("dbm");
        LOGGER.info("3组号码：{}-{}", dqm, dbm);
        /**
         * 开始点击需要下注的号码
         * 正常延时 900 毫秒
         * 异常延时 900 + 600 = 1500 毫秒（1.5秒）
         */
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[7]/tbody/tr[" + dqm + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[7]/tbody/tr[" + dqm + "]")).click();
            } catch (Exception e1) {
            }
        }
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[8]/tbody/tr[" + dbm + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[8]/tbody/tr[" + dbm + "]")).click();
            } catch (Exception e1) {
            }
        }
    }

    public void table4(WebDriver driver, Map<String, Integer> bets, By tableNodes, String page) throws Exception {
        assertionOneToTen(driver);

        String text = closed(driver);
        if (StringUtils.isEmpty(text)) {
            open(page);
        }
        if (text.equals("已封盘")) {
            groupOrder.put(page, 0);
            LOGGER.info(page + "已封盘,已下{}", groupOrder.get(page));
            startBet(driver, page);
        }

        clearBet(driver, tableNodes, Arrays.asList("9"));

        Integer djm = bets.get("djm");
        LOGGER.info("4组号码：{}", djm);
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[9]/tbody/tr[" + djm + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[9]/tbody/tr[" + djm + "]")).click();
            } catch (Exception e1) {
            }
        }
    }

    public void table5(WebDriver driver, Map<String, Integer> bets, By tableNodes, String page) throws Exception {
        assertionOneToTen(driver);

        String text = closed(driver);
        if (StringUtils.isEmpty(text)) {
            open(page);
        }
        if (text.equals("已封盘")) {
            groupOrder.put(page, 0);
            LOGGER.info(page + "已封盘,已下{}", groupOrder.get(page));
            startBet(driver, page);
        }

        clearBet(driver, tableNodes, Arrays.asList("10"));

        Integer dsm__ = bets.get("dsm__");
        LOGGER.info("5组号码：{}", dsm__);
        Thread.sleep(300);
        try {
            driver.findElement(tableNodes.xpath("//table[10]/tbody/tr[" + dsm__ + "]")).click();
        } catch (Exception e) {
            Thread.sleep(200);
            try {
                driver.findElement(tableNodes.xpath("//table[10]/tbody/tr[" + dsm__ + "]")).click();
            } catch (Exception e1) {
            }
        }
    }

    public void assertionOneToTen(WebDriver driver) throws InterruptedException {
        String oneToTen = null;
        try {
            oneToTen = driver.findElement(By.xpath("/html/body/app-root/app-game/div/div[2]/div[2]/app-play/div[1]/a[@class='active']")).getText();
        } catch (Exception e) {
        }
        if (StringUtils.isEmpty(oneToTen) || !oneToTen.equals("单号1~10")) {
            clickOneToTen(driver);
        }
    }

    /**
     *
     */
    public void over() {
        if (groupOrder.values().stream().distinct().collect(Collectors.toList()).size() < 2) {
            bets = randomUtil(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
            LOGGER.info("重新计算");
        }
    }

    public void useTime(String time, String page) {
        long pageTime = startTime.get(page);
        if (groupOrder.values().stream().distinct().collect(Collectors.toList()).size() < 2) {
            bets = randomUtil(Arrays.asList(1, 2, 3, 4, 5, 6, 7, 8, 9, 10));
            LOGGER.info("重新计算");
        }
    }

    /**
     * 点击单号1-10
     *
     * @param driver
     * @throws InterruptedException
     */
    public void clickOneToTen(WebDriver driver) throws InterruptedException {
        try {
            Thread.sleep(1000);
            driver.findElement(By.xpath("//div[@class='play-type']/a[2]")).click();
        } catch (Exception e) {
            Thread.sleep(1000);
            try {
                driver.findElement(By.cssSelector("body > app-root > app-game > div > div.container-right > div.play-main > app-play > div.play-type > a:nth-child(2)")).click();
            } catch (Exception e1) {
            }
        }
        JavascriptExecutor js = (JavascriptExecutor) driver;
        js.executeScript("scrollTo(0,200)");
    }

    public void clearBet(WebDriver driver, By tableNodes, List<String> clearTarget) {
        String resNode = driver.getPageSource();
        Document document = Jsoup.parse(resNode);
        String pNode = "body > app-root > app-game > div > div.container-right > div.play-main > app-play > div.game-main > div.game-body > div.bet-table > div > div > ";

        for (String s : clearTarget) {
            Elements elements1 = document.select(pNode + "table:nth-child(" + s + ") > tbody > tr.add");
            for (Element element : elements1) {
                try {
                    driver.findElement(By.cssSelector(element.cssSelector())).click();
                } catch (Exception e) {
                }
            }

            try {
                Thread.sleep(500);
                driver.findElement(tableNodes.xpath("//table[" + s + "]/tbody/tr[@class='add']")).click();
            } catch (Exception e) {
                try {
                    driver.findElement(tableNodes.cssSelector("table:nth-child(" + s + ") > tbody > tr.add")).click();
                } catch (Exception e1) {
                }
            }
        }
    }

    /**
     * 判断是否有多选或漏选
     *
     * @param driver
     * @param st
     * @throws InterruptedException
     */
    public boolean againSelect(WebDriver driver, int st) {
        try {
            String res = driver.getPageSource();
            String pNode = "body > app-root > app-game > div > div.container-right > div.play-main > app-play > div.game-main > div.game-body > div.bet-table > div > div > ";
            Document document = Jsoup.parse(res);
            if (st == 1) {
                Elements elements1 = document.select(pNode + "table:nth-child(1) > tbody > tr.add");
                Elements elements2 = document.select(pNode + "table:nth-child(2) > tbody > tr.add");
                Elements elements3 = document.select(pNode + "table:nth-child(3) > tbody > tr.add");
                if (elements1.size() != 1 || elements2.size() != 1 || elements3.size() != 1) {
                    return true;
                }
            }
            if (st == 2) {
                Elements elements1 = document.select(pNode + "table:nth-child(4) > tbody > tr.add");
                Elements elements2 = document.select(pNode + "table:nth-child(5) > tbody > tr.add");
                Elements elements3 = document.select(pNode + "table:nth-child(6) > tbody > tr.add");
                if (elements1.size() != 1 || elements2.size() != 1 || elements3.size() != 1) {
                    return true;
                }
            }
            if (st == 3) {
                Elements elements1 = document.select(pNode + "table:nth-child(7) > tbody > tr.add");
                Elements elements2 = document.select(pNode + "table:nth-child(8) > tbody > tr.add");
                if (elements1.size() != 1 || elements2.size() != 1) {
                    return true;
                }
            }
            if (st == 4) {
                Elements elements1 = document.select(pNode + "table:nth-child(9) > tbody > tr.add");
                if (elements1.size() != 1) {
                    return true;
                }
            }
            if (st == 5) {
                Elements elements1 = document.select(pNode + "table:nth-child(10) > tbody > tr.add");
                if (elements1.size() != 1) {
                    return true;
                }
            }
        } catch (Exception e) {
            LOGGER.info("1下注异常，重新下");
            return false;
        }
        return false;
    }

    /**
     * 重新打开
     *
     * @param driver
     * @param page
     * @throws Exception
     */
    public void reOpen(WebDriver driver, String page) throws Exception {
        if (refreshNum.get(page) < 5) {
            refreshNum.put(page, refreshNum.get(page) + 1);
            driver.close();
            open(page);
        }
    }

}
